﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Runtime.InteropServices;

namespace Slja.SMS
{
    /*
     * 来源：百度空间，“独来读网”的文章
     * 
     */
    public class DllInvoke
    {
        /* DllImport里面只能用字符串常量，而不能够用Server.MapPath(@"~/Bin/Judge.dll")来确定物理路径。
      经过一翻研究，终于想到了一个完美的解决办法
      首先我们用*/
        [DllImport("kernel32.dll")]
        private extern static IntPtr LoadLibrary(String path);
        [DllImport("kernel32.dll")]
        private extern static IntPtr GetProcAddress(IntPtr lib, String funcName);
        [DllImport("kernel32.dll")]
        private extern static bool FreeLibrary(IntPtr lib);
        /*
        分别取得了LoadLibrary和GetProcAddress函数的地址，再通过这两个函数来取得我们的DLL里面的函数。
        我们可以先用 Server.MapPath(@"~/Bin/Judge.dll")来取得我们的DLL的物理路径，然后再用LoadLibrary进行载入，最后用 GetProcAddress取得要用的函数地址
        以下自定义类的代码完成LoadLibrary的装载和函数调用
                 * */
        private IntPtr hLib;
        public DllInvoke(String DLLPath)
        {
            hLib = LoadLibrary(DLLPath);
        }
        ~DllInvoke()
        {
            FreeLibrary(hLib);
        }
        // 将要执行的函数转换为委托
        public Delegate Invoke(String APIName, Type t)
        {
            IntPtr api = GetProcAddress(hLib, APIName);
            return (Delegate)Marshal.GetDelegateForFunctionPointer(api, t);
        }

         /* 下面代码进行调用 */
        /*
        public delegate int Compile(String command, StringBuilder inf);// 编译
        DllInvoke dll ＝ new DllInvoke(Server.MapPath(@"~/Bin/Judge.dll"));
        Compile compile = (Compile)dll.Invoke("Compile", typeof(Compile));
        StringBuilder inf;
        compile(@"gcc a.c -o a.exe",inf); // 这里就是调用我的DLL里定义的Compile函数
             * */
    }
}